home *** CD-ROM | disk | FTP | other *** search
/ Mac Format 1994 October / Macformat17.cdr / Shareware City / Developers / MacVogl-alpha1PPC / htext.c < prev    next >
Text File  |  1994-07-11  |  12KB  |  709 lines

  1. /*
  2.  * This file is directly from the VOGLE library. It's simply had a few
  3.  * gratuitous name changes and some comments added.
  4.  */
  5. #ifdef SGI
  6. #include <gl.h>
  7. #include <device.h>
  8. #else
  9. #include "vogl.h"
  10. #include "vodevice.h"
  11. #endif
  12.  
  13. #include <stdio.h>
  14. #include <fcntl.h>
  15. #ifdef TC
  16. extern double sin();
  17. extern double cos();
  18. #else
  19. #include <math.h>
  20. #endif
  21. #include <string.h>
  22.  
  23. #ifndef PATH_SIZE
  24. #define    PATH_SIZE    256
  25. #endif
  26.  
  27. #ifdef MAC
  28. #ifndef FONTLIB
  29. #define FONTLIB        ":fonts:"
  30. #endif
  31. #else
  32. #ifdef PC
  33. #ifndef FONTLIB
  34. #define    FONTLIB        "c:\\lib\\hershey\\"
  35. #endif
  36. #else
  37. #ifndef FONTLIB
  38. #define    FONTLIB        "/usr/local/lib/hershey/"
  39. #endif
  40. #endif
  41. #endif
  42.  
  43. #define    ABS(a)        ((a) < 0 ? -(a) : (a))
  44. #define    MAX(a, b)    ((a) < (b) ? (b) : (a))
  45. #define    XCOORD(x)    (int)((x) - 'R')
  46. #define    YCOORD(y)    (int)('R' - (y))
  47.  
  48. #ifndef PI
  49. #define PI     3.14159265358979
  50. #endif
  51.  
  52. #ifndef D2R
  53. #define D2R    (PI / 180.0)
  54. #endif
  55.  
  56. #define LEFT        0    /* The default */
  57. #define CENTERED    1
  58. #define RIGHT        2
  59.  
  60. static    double    tcos = 1.0, tsin = 0.0;            /* For rotations */
  61. static    double    SCSIZEX = 1.0, SCSIZEY = 1.0;        /* Scale factors */
  62. static    int    Justify = LEFT;
  63. static    int    Fixedwidth = 0;            /* Some flags     */
  64. static    short    nchars;                    /* No. in font     */
  65. int    hLoaded = 0;
  66.  
  67. static    hershfont();
  68.  
  69. static    char    old_font[PATH_SIZE] = "";    /* So we don't have to reload it */
  70. static    char    fpath[PATH_SIZE] = "";    
  71.  
  72. #ifdef MAC
  73.     short macHersheyFontsVRefNum;
  74. #endif
  75.  
  76. static    struct    {
  77.     int    as;    /* Max ascender of a character in this font */
  78.     int    dec;    /* Max decender of a character in this font */
  79.     int    mw;    /* Max width of a character in this font */
  80.     char    *p;    /* All the vectors in the font */
  81.     char    **ind;    /* Pointers to where the chars start in p */
  82. } ftab;
  83.  
  84. double    hstrlength();    /* Length of a set of Hershey characters  */
  85. double    hgetfontwidth(); /* The width of this font */
  86. double    hgetfontheight(); /* The height of this font */
  87. extern    char    *hallocate();
  88. extern    char    *getenv();
  89.  
  90. /*
  91.  * hfont
  92.  *     loads in a hershey font.
  93.  */
  94. void
  95. hfont(name)
  96.     char    *name;
  97. {
  98.     /*
  99.      * check we aren't loading the same font twice in a row
  100.      */
  101.     if (*name == '/') {
  102.         if (strcmp(strrchr(name, '/') + 1, old_font) == 0)
  103.             return;
  104.  
  105.     } else if (strcmp(name, old_font) == 0)
  106.         return;
  107.  
  108.     /*
  109.      * Try and load it
  110.      */
  111.     if (!hershfont(name)) {
  112.         fprintf(stderr, "hershlib: problem reading font file '%s'.\n", name);
  113.         exit(1);
  114.     }
  115.  
  116.     /*
  117.      * Save the name of it...
  118.      */
  119.     if (*name == '/')
  120.         strcpy(old_font, strrchr(name, '/') + 1);
  121.     else 
  122.         strcpy(old_font, name);
  123.  
  124. }
  125.  
  126. /*
  127.  * hnumchars
  128.  *
  129.  *    Return the number of characters in the currently loaded hershey font.
  130.  */
  131. int
  132. hnumchars()
  133. {
  134.  
  135.     check_loaded("hnumchars");
  136.  
  137.     return((int)nchars);
  138. }
  139.  
  140. /*
  141.  * hsetpath
  142.  *
  143.  *    Set the path of the directory to look for fonts.
  144.  */
  145. void
  146. hsetpath(path)
  147.     char    *path;
  148. {
  149.     int    l;
  150.  
  151.     strcpy(fpath, path);
  152.  
  153.     l = strlen(fpath);
  154.  
  155. #ifdef MAC
  156. #else
  157. #ifdef PC
  158.     if (fpath[l] != '\\')
  159.         strcat(fpath, "\\");
  160. #else
  161.     if (fpath[l] != '/')
  162.         strcat(fpath, "/");
  163. #endif
  164. #endif
  165. }
  166.  
  167. /*
  168.  * hershfont
  169.  *
  170.  * Load in a hershey font. First try the environment, then the font library,
  171.  * if that fails try the current directory, otherwise return 0.
  172.  */
  173. static int
  174. hershfont(fontname)
  175.     char    *fontname;
  176. {
  177.     FILE    *fp, *fopen();
  178.     int    i, j;
  179.     short    nvects, n;
  180.     char    *flib;
  181.     char    path[PATH_SIZE];    
  182.     
  183.     if (fpath[0] != '\0') {
  184.         strcpy(path, fpath);
  185.         strcat(path, fontname);
  186.     } else if ((flib = getenv("HFONTLIB")) != (char *)NULL) {
  187.         strcpy(path, flib);
  188. #ifdef MAC
  189. #else
  190. #ifdef PC
  191.         strcat(path, "\\");
  192. #else
  193.         strcat(path, "/");
  194. #endif
  195. #endif
  196.         strcat(path, fontname);
  197.     } else if ((flib = getenv("VFONTLIB")) != (char *)NULL) {
  198.         strcpy(path, flib);    /* To be compatible with VOGLE */
  199. #ifdef MAC
  200. #else
  201. #ifdef PC
  202.         strcat(path, "\\");
  203. #else
  204.         strcat(path, "/");
  205. #endif
  206. #endif
  207.         strcat(path, fontname);
  208.     } else {
  209.         strcpy(path, FONTLIB);
  210. #ifdef MAC
  211. #else
  212. #ifdef PC
  213.         strcat(path, "\\");
  214. #else
  215.         strcat(path, "/");
  216. #endif
  217. #endif
  218.         strcat(path, fontname);
  219.     }
  220.  
  221. #ifdef PC
  222.     if ((fp = fopen(path, "r+b")) == (FILE *)NULL) 
  223.         if ((fp = fopen(fontname, "r+b")) == (FILE *)NULL) {
  224. #else
  225.     if ((fp = fopen(path, "r")) == (FILE *)NULL)
  226.         if ((fp = fopen(fontname, "r")) == (FILE *)NULL) {
  227. #endif
  228.             fprintf(stderr, "hershlib: Can't open Hershey fontfile '%s' or './%s'.\n", path, fontname);
  229.             exit(1);
  230.         }
  231.  
  232.     if (fread(&nchars, sizeof(nchars), 1, fp) != 1)
  233.         return (0);
  234.  
  235. #ifdef DEBUG
  236.     printf("nchars = %d\n", nchars);
  237. #endif
  238.  
  239.     if (fread(&nvects, sizeof(nvects), 1, fp) != 1)
  240.         return(0);
  241.  
  242. #ifdef DEBUG
  243.     printf("nvects = %d\n", nvects);
  244. #endif
  245.     if (fread(&n, sizeof(n), 1,  fp) != 1)
  246.         return(0);
  247.  
  248. #ifdef DEBUG
  249.     printf("ftab.as = %d\n", n);
  250. #endif
  251.     ftab.as = (int)n;
  252.  
  253.     if (fread(&n, sizeof(n), 1, fp) != 1)
  254.         return(0);
  255.  
  256. #ifdef DEBUG
  257.     printf("ftab.dec = %d\n", n);
  258. #endif
  259.     ftab.dec = (int)n;
  260.  
  261.     if (fread(&n, sizeof(n), 1, fp) != 1)
  262.         return(0);
  263.  
  264. #ifdef DEBUG
  265.     printf("ftab.mw = %d\n", n);
  266. #endif
  267.  
  268.     ftab.mw = (int)n;
  269.  
  270.     /*
  271.      *  Allocate space for it all....
  272.      */
  273.     if (hLoaded) {
  274.         if (ftab.ind[0])
  275.             free(ftab.ind[0]);
  276.         if (ftab.ind)
  277.             free(ftab.ind);
  278.         hLoaded = 0;
  279.     }
  280.  
  281.     ftab.ind = (char **)hallocate(sizeof(char *)*(nchars + 1));
  282.  
  283.     ftab.p = (char *)hallocate((unsigned)(2 * nvects));
  284.  
  285.     /*
  286.      *  As we read in each character, figure out what ind should be
  287.      */
  288.  
  289.     for (i = 0; i < nchars; i++) {
  290.         if (fread(&n , sizeof(n), 1, fp) != 1)
  291.             return(0);
  292.  
  293.         if (fread(ftab.p, 1, (unsigned)n, fp) != (unsigned)n)
  294.             return(0);
  295.  
  296.         ftab.ind[i] = ftab.p;
  297.         ftab.p += n;
  298.     }
  299.  
  300.     ftab.ind[nchars] = ftab.p;    /* To Terminate the last one */
  301.  
  302.     fclose(fp);
  303.     hLoaded = 1;
  304.     return(1);
  305. }
  306.  
  307. /*
  308.  * hgetcharsize
  309.  *
  310.  *    get the width and height of a single character. At the moment, for
  311.  * the hershey characters, the height returned is always that of the
  312.  * difference between the maximun descender and ascender.
  313.  *
  314.  */
  315. void
  316. hgetcharsize(c, width, height)
  317.     char    c;
  318.     double    *width, *height;
  319. {
  320.     check_loaded("hgetcharsize");
  321.     
  322.     *height = (double)(ftab.as - ftab.dec) * SCSIZEY;
  323.  
  324.     if (Fixedwidth)
  325.         *width = (double)ftab.mw * SCSIZEX;
  326.     else
  327.         *width = (double)(ftab.ind[c - 32][1] - ftab.ind[c - 32][0]) * SCSIZEX;
  328. }
  329.  
  330. /*
  331.  * hdrawchar
  332.  *
  333.  * Display a character from the currently loaded font.
  334.  */
  335. void
  336. hdrawchar(c)
  337.     int    c;
  338. {
  339.     char    *p, *e;
  340.     int    Move, i, x, y, xt, yt;
  341.     double    xs, ys, xp, yp, tmp, xtmp, ytmp;
  342.  
  343.     check_loaded("hdrawchar");
  344.  
  345.     if ((i = c - 32) < 0)
  346.         i = 0;
  347.     if (i >= nchars)
  348.         i = nchars - 1;
  349.  
  350.     Move = 1;
  351.  
  352.     xt = yt = 0;
  353.     if (Justify == LEFT) {
  354.         xt = (Fixedwidth ? -ftab.mw / 2 : XCOORD(ftab.ind[i][0]));
  355.         yt = ftab.dec;
  356.     } else if (Justify == RIGHT) {
  357.         xt = (Fixedwidth ?  ftab.mw / 2 : -XCOORD(ftab.ind[i][0]));
  358.         yt = ftab.dec;
  359.     }
  360.  
  361.     e = ftab.ind[i + 1];
  362.     p = ftab.ind[i] + 2;
  363.  
  364.     xtmp = ytmp = 0.0;
  365.  
  366.     while(p < e) {
  367.         x = XCOORD((int)*p++);
  368.         y = YCOORD((int)*p++);
  369.         if (x != -50) {            /* means move */
  370.             xp = (double)(x - xt) * SCSIZEX;
  371.             yp = (double)(y - yt) * SCSIZEY;
  372.             tmp = xp;
  373.             xp = tcos*tmp - tsin*yp;
  374.             yp = tsin*tmp + tcos*yp;
  375.             xs = xp - xtmp;
  376.             ys = yp - ytmp;
  377.             xtmp = xp;
  378.             ytmp = yp;
  379.             if (Move) {
  380.                 Move = 0;
  381.                 rmv((Coord)xs, (Coord)ys, (Coord)0.0);
  382.             } else
  383.                 rdr((Coord)xs, (Coord)ys, (Coord)0.0);
  384.  
  385.         } else {
  386.             Move = 1;
  387.         }
  388.     }
  389.     /*
  390.      * Move to right hand of character.
  391.        BLARK
  392.      */
  393.     
  394.     tmp = Fixedwidth ? (double)ftab.mw : (double)(ftab.ind[i][1] - ftab.ind[i][0]);
  395.  
  396.     tmp *= SCSIZEX;
  397.     xs = tcos * tmp - xtmp;
  398.     ys = tsin * tmp - ytmp;
  399.     rmv((Coord)xs, (Coord)ys, 0.0);
  400. }
  401.  
  402. /*
  403.  * htextsize
  404.  *
  405.  * set software character scaling values 
  406.  *
  407.  * Note: Only changes software char size. Should be called
  408.  * after a font has been loaded.
  409.  *
  410.  */
  411. void
  412. htextsize(width, height)
  413.     double    width, height;
  414. {
  415.     double    a;
  416.  
  417.     check_loaded("htextsize");
  418.  
  419.     a = (double)MAX((int)ftab.mw, (int)(ftab.as - ftab.dec));
  420.  
  421.     SCSIZEX = width / ABS(a);
  422.     SCSIZEY = height / ABS(a);
  423. }
  424.  
  425. /*
  426.  * hgetfontwidth
  427.  *
  428.  * Return the maximum Width of the current font.
  429.  *
  430.  */
  431. double
  432. hgetfontwidth()
  433. {
  434.     check_loaded("hgetfontwidth");
  435.  
  436.     return((double)(SCSIZEX * MAX((int)ftab.mw, (int)(ftab.as - ftab.dec))));
  437. }
  438.  
  439. /* 
  440.  * hgetfontheight
  441.  *
  442.  * Return the maximum Height of the current font
  443.  */
  444. double 
  445. hgetfontheight()
  446. {
  447.     check_loaded("hgetfontheight");
  448.  
  449.     return((double)(SCSIZEY * MAX((int)ftab.mw, (int)(ftab.as - ftab.dec))));
  450. }
  451.  
  452. /*
  453.  * hgetfontsize
  454.  *
  455.  * Get the current character size in user coords.
  456.  * For software Hershey fonts, the character width is that of
  457.  * a the widest character and the height the height of the tallest.
  458.  *
  459.  */
  460. void
  461. hgetfontsize(cw, ch)
  462.     double     *cw, *ch;
  463. {
  464.     check_loaded("hgetfontsize");
  465.  
  466.     *cw = hgetfontwidth();
  467.     *ch = hgetfontheight();
  468. }
  469.  
  470. /*
  471.  * hgetdecender
  472.  *
  473.  *    Return the maximum decender of the current font.
  474.  *     (In world coords).
  475.  */
  476. double
  477. hgetdecender()
  478. {
  479.     check_loaded("hgetdecender");
  480.  
  481.     return((double)ftab.dec * SCSIZEY);
  482. }
  483.  
  484. /*
  485.  * hgetascender
  486.  *
  487.  *    Return the maximum assender of the current font.
  488.  *     (In world coords).
  489.  */
  490. double
  491. hgetascender()
  492. {
  493.     check_loaded("hgetascender");
  494.  
  495.     return((double)ftab.as * SCSIZEY);
  496. }
  497.  
  498. /*
  499.  * hcharstr
  500.  *
  501.  * Draw a string from the current pen position.
  502.  *
  503.  */
  504. void
  505. hcharstr(string)
  506.     char     *string;
  507. {
  508.     double    width, height, cx, cy, cz;
  509.     char    *str = string, c;
  510.     int    oldJustify;
  511.  
  512.     check_loaded("hcharstr");
  513.  
  514.     height = hgetfontheight();
  515.     width = hstrlength(string);
  516.  
  517.     cx = cy = 0.0;
  518.     if (Justify == CENTERED) {
  519.         height /= 2.0;
  520.         width /= 2.0;
  521.         cx =  height * tsin - width * tcos;
  522.         cy = -height * tcos - width * tsin;
  523.     } else if (Justify == RIGHT) {
  524.         height = 0.0;
  525.         cx =  height * tsin - width * tcos;
  526.         cy = -height * tcos - width * tsin;
  527.     }
  528.     rmv((Coord)cx, (Coord)cy, (Coord)0.0);
  529.  
  530.  
  531.     /*
  532.      * For the duration of hershey strings, turn off
  533.      * "Justify" as we have already compensated
  534.      * for it in hcharstr()
  535.      */
  536.     oldJustify = Justify;
  537.     Justify = 0;
  538.  
  539.     /*
  540.      * Now display each character
  541.      *
  542.      */
  543.     while (c = *str++)
  544.         hdrawchar(c);
  545.     
  546.     Justify = oldJustify;
  547.  
  548. }
  549.  
  550. /*
  551.  * istrlength
  552.  *
  553.  * Find out the length of a string in raw "Hershey coordinates".
  554.  */
  555. static    int
  556. istrlength(s)
  557.     char    *s;
  558. {
  559.     char    c;
  560.     int    i, len = 0;
  561.     
  562.     if (Fixedwidth)
  563.         return((int)(strlen(s) * ftab.mw));
  564.     else {
  565.         while (c = *s++) {
  566.             if ((i = (int)c - 32) < 0 || i >= nchars)
  567.                 i = nchars - 1;
  568.  
  569.             len += (ftab.ind[i][1] - ftab.ind[i][0]);
  570.         }
  571.         return (len);
  572.     }
  573. }
  574.  
  575. /*
  576.  * hstrlength
  577.  *
  578.  * Find out the length (in world coords) of a string.
  579.  *
  580.  */
  581. double
  582. hstrlength(s)
  583.     char    *s;
  584. {
  585.     check_loaded("hstrlength");
  586.  
  587.     return((double)(istrlength(s) * SCSIZEX));
  588. }
  589.  
  590. /*
  591.  * hboxtext
  592.  *
  593.  * Draw text so it fits in a "box" - note only works with hershey text
  594.  */
  595. void
  596. hboxtext(x, y, l, h, s)
  597.     double    x, y, l, h;
  598.     char    *s;
  599. {
  600.     double    oscsizex, oscsizey, cz;
  601.  
  602.     check_loaded("hboxtext");
  603.  
  604.     oscsizex = SCSIZEX;
  605.     oscsizey = SCSIZEY;
  606.     /*
  607.      * set width so string length is the same a "l" 
  608.      */
  609.     SCSIZEX = l / (double)istrlength(s);
  610.  
  611.     /* 
  612.      * set character height so it's the same as "h" 
  613.      */
  614.     SCSIZEY = h / (double)(ftab.as - ftab.dec);
  615.  
  616.     move2(x, y);
  617.     hcharstr(s);
  618.  
  619.     SCSIZEX = oscsizex;
  620.     SCSIZEY = oscsizey;
  621. }
  622.  
  623. /*
  624.  * hboxfit
  625.  *
  626.  * Set up the scales etc for text so that a string of "nchars" characters
  627.  * of the maximum width in the font fits in a box.
  628.  */
  629. void
  630. hboxfit(l, h, nchars)
  631.     double    l, h;
  632.     int    nchars;
  633. {
  634.     check_loaded("hboxfit");
  635.  
  636.     SCSIZEX = l / (double)(nchars * ftab.mw);
  637.     SCSIZEY = h / (double)(ftab.as - ftab.dec);
  638. }
  639.  
  640. /*
  641.  * The following can be set without a font actually being loaded....
  642.  */
  643. /*
  644.  * hcenter
  645.  *
  646.  *    Turns centering of text on or off
  647.  */
  648. void
  649. hcentertext(onoff)
  650.     int    onoff;
  651. {
  652.     Justify = (onoff != 0 ? CENTERED : LEFT);
  653. }
  654.  
  655. /*
  656.  * hrightjustify
  657.  *
  658.  *    Right Justifies the text.
  659.  */
  660. void
  661. hrightjustify(onoff)
  662.     int    onoff;
  663. {
  664.     Justify = (onoff != 0 ? RIGHT : LEFT);
  665. }
  666.  
  667. /*
  668.  * hleftjustify
  669.  *
  670.  *    Left Justifies the text. (the default).
  671.  */
  672. void
  673. hleftjustify(onoff)
  674.     int    onoff;
  675. {
  676.     Justify = (onoff != 0 ? LEFT : RIGHT);
  677. }
  678.  
  679. /*
  680.  * fixedwidth
  681.  *
  682.  *    Turns fixedwidth text on or off
  683.  */
  684. void
  685. hfixedwidth(onoff)
  686.     int    onoff;
  687. {
  688.     Fixedwidth = onoff;
  689. }
  690.  
  691. /*
  692.  * htextang
  693.  *
  694.  * set software character angle in degrees
  695.  *
  696.  * strings will be written along a line 'ang' degrees from the 
  697.  * horizontal screen direction
  698.  *
  699.  * Note: only changes software character angle
  700.  *
  701.  */
  702. void
  703. htextang(ang)
  704.     double    ang;
  705. {
  706.     tcos = cos((double)(ang * D2R));
  707.     tsin = sin((double)(ang * D2R));
  708. }
  709.